#ifndef __BATENT_H__
#define __BATENT_H__

#include <cstdio>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <string>
#include <vector>
#include <list>
#include <algorithm>

#include <windows.h>

using namespace std;

#include "Util.h"
#include "FsCmd.h"
#include "StrCmd.h"
#include "DateCmd.h"
#include "MiscCmd.h"


namespace Batent
{
    class CmdObject
    {
    public:
        int minPara;
        int maxPara;
        string szCmd;
        string szDesc;
        CmdObject(const string &cmd, bool global = true);

        bool operator < (const CmdObject &right)
        {
            return szCmd < right.szCmd;
        }

        bool operator == (const CmdObject &right)
        {
            return szCmd == right.szCmd;
        }

        virtual int run(const vector<string> &args)
        {
            error("Couldn't use CmdObject directly\n");
            return -1;
        }

        virtual void help(void)
        {

        }

    };


    class CmdObjectRef
    {
    public:
        CmdObject *pCmd;
        CmdObjectRef() : pCmd(NULL)
        {
        }
        
        CmdObjectRef(CmdObject &Cmd) : pCmd(&Cmd)
        {
        }

        bool operator < (const CmdObjectRef &right) const 
        {
            return *pCmd < *(right.pCmd);
        }

        bool operator == (const CmdObjectRef &right) const 
        {
            return *pCmd == *(right.pCmd);
        }
        
        CmdObjectRef & operator = (const CmdObjectRef &right)
        {
            pCmd = right.pCmd;
            return *this;
        }

    };
}

#define CMD_INSTANSE(TYPE) TYPE TYPE##Obj

#define DECLARE_CMD_CLASS(NAME, min_para, max_para, cmdName, Desc) \
    class NAME : public CmdObject \
    {\
    public: \
        NAME() : CmdObject(cmdName) \
        {\
            CmdObject::minPara = min_para;\
            CmdObject::maxPara = max_para;\
            CmdObject::szDesc = Desc;\
        }\
        /* void help(void); */ \
        int run(const vector<string> &args);\
    };\
    CMD_INSTANSE(NAME)


#endif
